home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume23 / sc6.8 / part04 < prev    next >
Encoding:
Internet Message Format  |  1990-10-09  |  54.3 KB

  1. Subject:  v23i024:  The SC Spreadsheet, release 6.8, Part04/06
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 7f9d9dff a2a6a7c7 ba0c427b cf2b77a6
  5.  
  6. Submitted-by: Jeff Buhrt <sawmill!buhrt>
  7. Posting-number: Volume 23, Issue 24
  8. Archive-name: sc6.8/part04
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # Contents:  cmds.c lex.c psc.c xmalloc.c
  17. # Wrapped by rsalz@litchi.bbn.com on Fri Jul 13 15:24:21 1990
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. echo If this archive is complete, you will see the following message:
  20. echo '          "shar: End of archive 4 (of 6)."'
  21. if test -f 'cmds.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'cmds.c'\"
  23. else
  24.   echo shar: Extracting \"'cmds.c'\" \(30867 characters\)
  25.   sed "s/^X//" >'cmds.c' <<'END_OF_FILE'
  26. X/*    SC    A Spreadsheet Calculator
  27. X *        Command routines
  28. X *
  29. X *        original by James Gosling, September 1982
  30. X *        modifications by Mark Weiser and Bruce Israel,
  31. X *            University of Maryland
  32. X *
  33. X *              More mods Robert Bond, 12/86
  34. X *
  35. X *        $Revision: 6.8 $
  36. X */
  37. X
  38. X#include <curses.h>
  39. X#if defined(BSD42) || defined(BSD43)
  40. X#include <sys/file.h>
  41. X#else
  42. X#include <fcntl.h>
  43. X#endif
  44. X#include "sc.h"
  45. X#include <signal.h>
  46. X#include <errno.h>
  47. X
  48. X#ifdef BSD42
  49. X#include <strings.h>
  50. X#else
  51. X#ifndef SYSIII
  52. X#include <string.h>
  53. X#endif
  54. X#endif
  55. X
  56. X#ifdef SYSV3
  57. Xextern void exit();
  58. X#else
  59. Xextern int exit();
  60. X#endif
  61. X
  62. Xextern    int    errno;
  63. X
  64. X#define DEFCOLDELIM ':'
  65. X
  66. Xvoid
  67. Xduprow()
  68. X{
  69. X    if (currow >= maxrows - 1 || maxrow >= maxrows - 1) {
  70. X    if (!growtbl(GROWROW, 0, 0))
  71. X        return;
  72. X    }
  73. X    modflg++;
  74. X    currow++;
  75. X    openrow (currow);
  76. X    for (curcol = 0; curcol <= maxcol; curcol++) {
  77. X    register struct ent *p = *ATBL(tbl, currow - 1, curcol);
  78. X    if (p) {
  79. X        register struct ent *n;
  80. X        n = lookat (currow, curcol);
  81. X        (void)copyent ( n, p, 1, 0);
  82. X    }
  83. X    }
  84. X    for (curcol = 0; curcol <= maxcol; curcol++) {
  85. X    register struct ent *p = *ATBL(tbl, currow, curcol);
  86. X    if (p && (p -> flags & is_valid) && !p -> expr)
  87. X        break;
  88. X    }
  89. X    if (curcol > maxcol)
  90. X    curcol = 0;
  91. X}
  92. X
  93. Xvoid
  94. Xdupcol() 
  95. X{
  96. X    if (curcol >= maxcols - 1 || maxcol >= maxcols - 1) {
  97. X    if (!growtbl(GROWCOL, 0, 0))
  98. X        return;
  99. X    }
  100. X    modflg++;
  101. X    curcol++;
  102. X    opencol (curcol, 1);
  103. X    for (currow = 0; currow <= maxrow; currow++) {
  104. X    register struct ent *p = *ATBL(tbl, currow, curcol - 1);
  105. X    if (p) {
  106. X        register struct ent *n;
  107. X        n = lookat (currow, curcol);
  108. X        copyent ( n, p, 0, 1);
  109. X    }
  110. X    }
  111. X    for (currow = 0; currow <= maxrow; currow++) {
  112. X    register struct ent *p = *ATBL(tbl, currow, curcol);
  113. X    if (p && (p -> flags & is_valid) && !p -> expr)
  114. X        break;
  115. X    }
  116. X    if (currow > maxrow)
  117. X    currow = 0;
  118. X}
  119. X
  120. Xvoid
  121. Xinsertrow(arg)
  122. Xregister int arg;
  123. X{
  124. X    while (--arg>=0) openrow (currow);
  125. X}
  126. X
  127. Xvoid
  128. Xdeleterow(arg)
  129. Xregister int arg;
  130. X{
  131. X    flush_saved();
  132. X    erase_area(currow, 0, currow + arg - 1, maxcol);
  133. X    currow += arg;
  134. X    while (--arg>=0) closerow (--currow);
  135. X    sync_refs();
  136. X}
  137. X
  138. Xvoid
  139. Xrowvalueize(arg)
  140. Xregister int arg;
  141. X{
  142. X    valueize_area(currow, 0, currow + arg - 1, maxcol);
  143. X}
  144. X
  145. Xvoid
  146. Xcolvalueize(arg)
  147. Xregister int arg;
  148. X{
  149. X    valueize_area(0, curcol, maxrow, curcol + arg - 1);
  150. X}
  151. X
  152. Xvoid
  153. Xerase_area(sr, sc, er, ec)
  154. Xint sr, sc, er, ec;
  155. X{
  156. X    register int r, c;
  157. X    register struct ent **pp;
  158. X
  159. X    if (sr > er) {
  160. X    r = sr; sr = er; er= r;    
  161. X    }
  162. X
  163. X    if (sc > ec) {
  164. X    c = sc; sc = ec; ec= c;    
  165. X    }
  166. X
  167. X    if (sr < 0)
  168. X    sr = 0; 
  169. X    if (sc < 0)
  170. X    sc = 0;
  171. X    checkbounds(&er, &ec);
  172. X
  173. X    for (r = sr; r <= er; r++) {
  174. X    for (c = sc; c <= ec; c++) {
  175. X        pp = ATBL(tbl, r, c);
  176. X        if (*pp) {
  177. X        free_ent(*pp);
  178. X        *pp = (struct ent *)0;
  179. X        }
  180. X    }
  181. X    }
  182. X}
  183. X
  184. Xvoid
  185. Xvalueize_area(sr, sc, er, ec)
  186. Xint sr, sc, er, ec;
  187. X{
  188. X    register int r, c;
  189. X    register struct ent *p;
  190. X
  191. X    if (sr > er) {
  192. X    r = sr; sr = er; er= r;    
  193. X    }
  194. X
  195. X    if (sc > ec) {
  196. X    c = sc; sc = ec; ec= c;    
  197. X    }
  198. X
  199. X    if (sr < 0)
  200. X    sr = 0; 
  201. X    if (sc < 0)
  202. X    sc = 0;
  203. X    checkbounds(&er, &ec);
  204. X
  205. X    for (r = sr; r <= er; r++) {
  206. X    for (c = sc; c <= ec; c++) {
  207. X        p = *ATBL(tbl, r, c);
  208. X        if (p && p->expr) {
  209. X        efree(p, p->expr);
  210. X        p->expr = (struct enode *)0;
  211. X        p->flags &= ~is_strexpr;
  212. X        }
  213. X    }
  214. X    }
  215. X
  216. X}
  217. X
  218. Xvoid
  219. Xpullcells(to_insert)
  220. Xint to_insert;
  221. X{
  222. X    register struct ent *p, *n;
  223. X    register int deltar, deltac;
  224. X    int minrow, mincol;
  225. X    int mxrow, mxcol;
  226. X    int numrows, numcols;
  227. X
  228. X    if (! to_fix)
  229. X    {
  230. X    error ("No data to pull");
  231. X    return;
  232. X    }
  233. X
  234. X    minrow = maxrows; 
  235. X    mincol = maxcols;
  236. X    mxrow = 0;
  237. X    mxcol = 0;
  238. X
  239. X    for (p = to_fix; p; p = p->next) {
  240. X    if (p->row < minrow)
  241. X        minrow = p->row;
  242. X    if (p->row > mxrow)
  243. X        mxrow = p->row;
  244. X    if (p->col < mincol)
  245. X        mincol = p->col;
  246. X    if (p->col > mxcol)
  247. X        mxcol = p->col;
  248. X    }
  249. X
  250. X    numrows = mxrow - minrow + 1;
  251. X    numcols = mxcol - mincol + 1;
  252. X    deltar = currow - minrow;
  253. X    deltac = curcol - mincol;
  254. X
  255. X    if (to_insert == 'r') {
  256. X    insertrow(numrows);
  257. X    deltac = 0;
  258. X    } else if (to_insert == 'c') {
  259. X    opencol(curcol, numcols);
  260. X    deltar = 0;
  261. X    }
  262. X
  263. X    FullUpdate++;
  264. X    modflg++;
  265. X
  266. X    for (p = to_fix; p; p = p->next) {
  267. X    n = lookat (p->row + deltar, p->col + deltac);
  268. X    (void) clearent(n);
  269. X    copyent( n, p, deltar, deltac);
  270. X    n -> flags = p -> flags & ~is_deleted;
  271. X    }
  272. X}
  273. X
  274. Xvoid
  275. Xcolshow_op()
  276. X{
  277. X    register int i,j;
  278. X    for (i=0; i<maxcols; i++)
  279. X    if (col_hidden[i]) 
  280. X        break;
  281. X    for(j=i; j<maxcols; j++)
  282. X    if (!col_hidden[j])
  283. X        break;
  284. X    j--;
  285. X    if (i>=maxcols)
  286. X    error ("No hidden columns to show");
  287. X    else {
  288. X    (void) sprintf(line,"show %s:", coltoa(i));
  289. X    (void) sprintf(line + strlen(line),"%s",coltoa(j));
  290. X    linelim = strlen (line);
  291. X    }
  292. X}
  293. X
  294. Xvoid
  295. Xrowshow_op()
  296. X{
  297. X    register int i,j;
  298. X    for (i=0; i<maxrows; i++)
  299. X    if (row_hidden[i]) 
  300. X        break;
  301. X    for(j=i; j<maxrows; j++)
  302. X    if (!row_hidden[j]) {
  303. X        break;
  304. X    }
  305. X    j--;
  306. X
  307. X    if (i>=maxrows)
  308. X    error ("No hidden rows to show");
  309. X    else {
  310. X    (void) sprintf(line,"show %d:%d", i, j);
  311. X        linelim = strlen (line);
  312. X    }
  313. X}
  314. X
  315. X/*
  316. X * Given a row/column command letter, emit a small menu, then read a qualifier
  317. X * character for a row/column command and convert it to 'r' (row), 'c'
  318. X * (column), or 0 (unknown).  If ch is 'p', an extra qualifier 'm' is allowed.
  319. X */
  320. X
  321. Xint
  322. Xget_rcqual (ch)
  323. X    int ch;
  324. X{
  325. X    error ("%sow/column:  r: row  c: column%s",
  326. X
  327. X        (ch == 'i') ? "Insert r" :
  328. X        (ch == 'a') ? "Append r" :
  329. X        (ch == 'd') ? "Delete r" :
  330. X        (ch == 'p') ? "Pull r" :
  331. X        (ch == 'v') ? "Values r" :
  332. X        (ch == 'z') ? "Zap r" :
  333. X        (ch == 's') ? "Show r" : "R",
  334. X
  335. X        (ch == 'p') ? "  m: merge" : "");
  336. X
  337. X    (void) refresh();
  338. X
  339. X    switch (nmgetch())
  340. X    {
  341. X    case 'r':
  342. X    case 'l':
  343. X    case 'h':
  344. X    case ctl('f'):
  345. X    case ctl('b'):    return ('r');
  346. X
  347. X    case 'c':
  348. X    case 'j':
  349. X    case 'k':
  350. X    case ctl('p'):
  351. X    case ctl('n'):    return ('c');
  352. X
  353. X    case 'm':    return ((ch == 'p') ? 'm' : 0);
  354. X
  355. X    case ESC:
  356. X    case ctl('g'):    return (ESC);
  357. X
  358. X    default:    return (0);
  359. X    }
  360. X    /*NOTREACHED*/
  361. X}
  362. X
  363. Xvoid
  364. Xopenrow (rs)
  365. Xint    rs;
  366. X{
  367. X    register    r, c;
  368. X    struct ent    **tmprow, **pp;
  369. X
  370. X    if (rs > maxrow) maxrow = rs;
  371. X    if (maxrow >= maxrows - 1 || rs > maxrows - 1) {
  372. X    if (!growtbl(GROWROW, rs, 0))
  373. X        return;
  374. X    }
  375. X    /*
  376. X     * save the last active row+1, shift the rows downward, put the last
  377. X     * row in place of the first
  378. X     */
  379. X    tmprow = tbl[++maxrow];
  380. X    for (r = maxrow; r > rs; r--) {
  381. X    row_hidden[r] = row_hidden[r-1];
  382. X    tbl[r] = tbl[r-1];
  383. X    pp = ATBL(tbl, r, 0);
  384. X    for (c = 0; c < maxcols; c++, pp++)
  385. X        if (*pp)
  386. X            (*pp)->row = r;
  387. X    }
  388. X    tbl[r] = tmprow;    /* the last row was never used.... */
  389. X    FullUpdate++;
  390. X    modflg++;
  391. X}
  392. X
  393. Xvoid
  394. Xcloserow (r)
  395. Xregister r;
  396. X{
  397. X    register struct ent **pp;
  398. X    register c;
  399. X    struct ent    **tmprow;
  400. X
  401. X    if (r > maxrow) return;
  402. X
  403. X    /* save the row and empty it out */
  404. X    tmprow = tbl[r];
  405. X    pp = ATBL(tbl, r, 0);
  406. X    for (c=maxcol+1; --c>=0; pp++) {
  407. X    if (*pp)
  408. X    {    free_ent(*pp);
  409. X        *pp = (struct ent *)0;
  410. X    }
  411. X    }
  412. X
  413. X    /* move the rows, put the deleted row at the end */
  414. X    for (; r < maxrows - 1; r++) {
  415. X    row_hidden[r] = row_hidden[r+1];
  416. X    tbl[r] = tbl[r+1];
  417. X    pp = ATBL(tbl, r, 0);
  418. X    for (c = 0; c < maxcols; c++, pp++)
  419. X        if (*pp)
  420. X            (*pp)->row = r;
  421. X    }
  422. X    tbl[r] = tmprow;
  423. X
  424. X    maxrow--;
  425. X    FullUpdate++;
  426. X    modflg++;
  427. X}
  428. X
  429. Xvoid
  430. Xopencol (cs, numcol)
  431. Xint    cs;
  432. Xint    numcol;
  433. X{
  434. X    register r;
  435. X    register struct ent **pp;
  436. X    register c;
  437. X    register lim = maxcol-cs+1;
  438. X    int i;
  439. X
  440. X    if (cs > maxcol)
  441. X    maxcol = cs;
  442. X    maxcol += numcol;
  443. X
  444. X    if ((maxcol >= maxcols - 1) && !growtbl(GROWCOL, 0, maxcol))
  445. X        return;
  446. X
  447. X    for (i = maxcol; i > cs; i--) {
  448. X    fwidth[i] = fwidth[i-numcol];
  449. X    precision[i] = precision[i-numcol];
  450. X    col_hidden[i] = col_hidden[i-numcol];
  451. X    }
  452. X    for (c = cs; c - cs < numcol; c++)
  453. X    {    fwidth[c] = DEFWIDTH;
  454. X    precision[c] =  DEFPREC;
  455. X    }
  456. X    
  457. X    for (r=0; r<=maxrow; r++) {
  458. X    pp = ATBL(tbl, r, maxcol);
  459. X    for (c=lim; --c>=0; pp--)
  460. X        if (pp[0] = pp[-numcol])
  461. X        pp[0]->col += numcol;
  462. X
  463. X    pp = ATBL(tbl, r, cs);
  464. X    for (c = cs; c - cs < numcol; c++, pp++)
  465. X        *pp = (struct ent *)0;
  466. X    }
  467. X    FullUpdate++;
  468. X    modflg++;
  469. X}
  470. X
  471. Xvoid
  472. Xclosecol (cs, numcol)
  473. Xint cs;
  474. Xint    numcol;
  475. X{
  476. X    register r;
  477. X    register struct ent **pp;
  478. X    register struct ent *q;
  479. X    register c;
  480. X    register lim = maxcol-cs;
  481. X    int i;
  482. X    char buf[50];
  483. X
  484. X    if (lim - numcol < -1)
  485. X    {    sprintf(buf, "Can't delete %d column%s %d columns left", numcol,
  486. X            (numcol > 1 ? "s," : ","), lim+1);
  487. X    error(buf);
  488. X    return;
  489. X    }
  490. X    flush_saved();
  491. X    erase_area(0, curcol, maxrow, curcol + numcol - 1);
  492. X    sync_refs();
  493. X
  494. X    /* clear then copy the block left */
  495. X    lim = maxcols - numcol - 1;
  496. X    for (r=0; r<=maxrow; r++) {
  497. X    for (c = cs; c - cs < numcol; c++)
  498. X        if (q = *ATBL(tbl, r, c))
  499. X            free_ent(q);
  500. X
  501. X    pp = ATBL(tbl, r, cs);
  502. X    for (c=cs; c <= lim; c++, pp++)
  503. X    {   if (c > lim)
  504. X        *pp = (struct ent *)0;
  505. X        else
  506. X        if (pp[0] = pp[numcol])
  507. X        pp[0]->col -= numcol;
  508. X    }
  509. X
  510. X    c = numcol;
  511. X    for (; --c >= 0; pp++)        
  512. X        *pp = (struct ent *)0;
  513. X    }
  514. X
  515. X    for (i = cs; i < maxcols - numcol - 1; i++) {
  516. X    fwidth[i] = fwidth[i+numcol];
  517. X    precision[i] = precision[i+numcol];
  518. X    col_hidden[i] = col_hidden[i+numcol];
  519. X    }
  520. X    for (; i < maxcols - 1; i++) {
  521. X    fwidth[i] = DEFWIDTH;
  522. X    precision[i] = DEFPREC;
  523. X    col_hidden[i] = 0;
  524. X    }
  525. X
  526. X    maxcol -= numcol;
  527. X    FullUpdate++;
  528. X    modflg++;
  529. X}
  530. X
  531. Xvoid
  532. Xdoend(rowinc, colinc)
  533. Xint rowinc, colinc;
  534. X{
  535. X    register struct ent *p;
  536. X    int r, c;
  537. X
  538. X    if (VALID_CELL(p, currow, curcol)) {
  539. X    r = currow + rowinc;
  540. X    c = curcol + colinc;
  541. X    if (r >= 0 && r < maxrows && 
  542. X        c >= 0 && c < maxcols &&
  543. X        !VALID_CELL(p, r, c)) {
  544. X        currow = r;
  545. X        curcol = c;
  546. X    }
  547. X    }
  548. X
  549. X    if (!VALID_CELL(p, currow, curcol)) {
  550. X        switch (rowinc) {
  551. X        case -1:
  552. X        while (!VALID_CELL(p, currow, curcol) && currow > 0)
  553. X        currow--;
  554. X        break;
  555. X        case  1:
  556. X        while (!VALID_CELL(p, currow, curcol) && currow < maxrows-1)
  557. X        currow++;
  558. X        break;
  559. X        case  0:
  560. X            switch (colinc) {
  561. X         case -1:
  562. X            while (!VALID_CELL(p, currow, curcol) && curcol > 0)
  563. X            curcol--;
  564. X            break;
  565. X         case  1:
  566. X            while (!VALID_CELL(p, currow, curcol) && curcol < maxcols-1)
  567. X            curcol++;
  568. X            break;
  569. X        }
  570. X            break;
  571. X        }
  572. X
  573. X    error ("");    /* clear line */
  574. X    return;
  575. X    }
  576. X
  577. X    switch (rowinc) {
  578. X    case -1:
  579. X    while (VALID_CELL(p, currow, curcol) && currow > 0)
  580. X        currow--;
  581. X    break;
  582. X    case  1:
  583. X    while (VALID_CELL(p, currow, curcol) && currow < maxrows-1)
  584. X        currow++;
  585. X    break;
  586. X    case  0:
  587. X    switch (colinc) {
  588. X    case -1:
  589. X        while (VALID_CELL(p, currow, curcol) && curcol > 0)
  590. X        curcol--;
  591. X        break;
  592. X    case  1:
  593. X        while (VALID_CELL(p, currow, curcol) && curcol < maxcols-1)
  594. X        curcol++;
  595. X        break;
  596. X    }
  597. X    break;
  598. X    }
  599. X    if (!VALID_CELL(p, currow, curcol)) {
  600. X        currow -= rowinc;
  601. X        curcol -= colinc;
  602. X    }
  603. X}
  604. X
  605. Xvoid
  606. Xdoformat(c1,c2,w,p)
  607. Xint c1,c2,w,p;
  608. X{
  609. X    register int i;
  610. X
  611. X    if (w > COLS - RESCOL - 2) {
  612. X    error("Format too large - Maximum = %d", COLS - RESCOL - 2);
  613. X    w = COLS-RESCOL-2;
  614. X    }
  615. X
  616. X    if (p > w) {
  617. X    error("Precision too large");
  618. X    p = w;
  619. X    }
  620. X
  621. X    for(i = c1; i<=c2; i++)
  622. X    fwidth[i] = w, precision[i] = p;
  623. X
  624. X    FullUpdate++;
  625. X    modflg++;
  626. X}
  627. X
  628. Xvoid
  629. Xprint_options(f)
  630. XFILE *f;
  631. X{
  632. X    if(
  633. X       autocalc &&
  634. X       propagation == 10 &&
  635. X       calc_order == BYROWS &&
  636. X       !numeric &&
  637. X       prescale == 1.0 &&
  638. X       !extfunc &&
  639. X       showcell &&
  640. X       showtop &&
  641. X       tbl_style == 0
  642. X      )
  643. X        return;        /* No reason to do this */
  644. X
  645. X    (void) fprintf(f, "set");
  646. X    if(!autocalc) 
  647. X    (void) fprintf(f," !autocalc");
  648. X    if(propagation != 10)
  649. X    (void) fprintf(f, " iterations = %d", propagation);
  650. X    if(calc_order != BYROWS )
  651. X    (void) fprintf(f, " bycols");
  652. X    if (numeric)
  653. X    (void) fprintf(f, " numeric");
  654. X    if (prescale != 1.0)
  655. X    (void) fprintf(f, " prescale");
  656. X    if (extfunc)
  657. X    (void) fprintf(f, " extfun");
  658. X    if (!showcell)
  659. X    (void) fprintf(f, " !cellcur");
  660. X    if (!showtop)
  661. X    (void) fprintf(f, " !toprow");
  662. X    if (tbl_style)
  663. X    (void) fprintf(f, " tblstyle = %s", tbl_style == TBL ? "tbl" :
  664. X                    tbl_style == LATEX ? "latex" :
  665. X                    tbl_style == TEX ? "tex" : "0" );
  666. X    (void) fprintf(f, "\n");
  667. X}
  668. X
  669. Xvoid
  670. Xprintfile (fname, r0, c0, rn, cn)
  671. Xchar *fname;
  672. Xint r0, c0, rn, cn;
  673. X{
  674. X    FILE *f;
  675. X    char pline[FBUFLEN];
  676. X    int plinelim;
  677. X    int pid;
  678. X    int fieldlen, nextcol;
  679. X    register row, col;
  680. X    register struct ent **pp;
  681. X
  682. X    if ((strcmp(fname, curfile) == 0) &&
  683. X    !yn_ask("Confirm that you want to destroy the data base: (y,n)"))
  684. X    return;
  685. X
  686. X    if ((f = openout(fname, &pid)) == (FILE *)0)
  687. X    {    error ("Can't create file \"%s\"", fname);
  688. X    return;
  689. X    }
  690. X    for (row=r0;row<=rn; row++) {
  691. X    register c = 0;
  692. X
  693. X    if (row_hidden[row])
  694. X        continue;
  695. X
  696. X    pline[plinelim=0] = '\0';
  697. X    for (pp = ATBL(tbl, row, col=c0); col<=cn;
  698. X            pp += nextcol-col, col = nextcol, c += fieldlen) {
  699. X
  700. X        nextcol = col+1;
  701. X        if (col_hidden[col]) {
  702. X        fieldlen = 0;
  703. X        continue;
  704. X        }
  705. X
  706. X        fieldlen = fwidth[col];
  707. X        if (*pp) {
  708. X        char *s;
  709. X
  710. X        while (plinelim<c) pline[plinelim++] = ' ';
  711. X        plinelim = c;
  712. X        if ((*pp)->flags&is_valid) {
  713. X            (void)sprintf (pline+plinelim,"%*.*f",fwidth[col],
  714. X                                        precision[col], (*pp)->v);
  715. X            plinelim += strlen (pline+plinelim);
  716. X        }
  717. X        if (s = (*pp)->label) {
  718. X            int slen;
  719. X            char *start, *last;
  720. X            register char *fp;
  721. X            struct ent *nc;
  722. X
  723. X            /* Figure out if the label slops over to a blank field */
  724. X            slen = strlen(s);
  725. X            while (slen > fieldlen && nextcol <= cn &&
  726. X                !((nc = lookat(row,nextcol))->flags & is_valid) &&
  727. X                !(nc->label)) {
  728. X            
  729. X                    if (!col_hidden[nextcol])
  730. X                 fieldlen += fwidth[nextcol];
  731. X
  732. X            nextcol++;
  733. X            }
  734. X            if (slen > fieldlen)
  735. X            slen = fieldlen;
  736. X            
  737. X            /* Now justify and print */
  738. X            start = (*pp)->flags & is_leftflush ? pline + c
  739. X                    : pline + c + fieldlen - slen;
  740. X            last = pline + c + fieldlen;
  741. X            fp = plinelim < c ? pline + plinelim : pline + c;
  742. X            while (fp < start)
  743. X            *fp++ = ' ';
  744. X            while (slen--)
  745. X            *fp++ = *s++;
  746. X            if (!((*pp)->flags & is_valid) || fieldlen != fwidth[col])
  747. X            while(fp < last)
  748. X                *fp++ = ' ';
  749. X            if (plinelim < fp - pline)
  750. X            plinelim = fp - pline;
  751. X        }
  752. X        }
  753. X    }
  754. X    pline[plinelim++] = '\n';
  755. X    pline[plinelim] = '\0';
  756. X    (void) fputs (pline, f);
  757. X    }
  758. X
  759. X    closeout(f, pid);
  760. X}
  761. X
  762. Xvoid
  763. Xtblprintfile (fname, r0, c0, rn, cn)
  764. Xchar *fname;
  765. Xint r0, c0, rn, cn;
  766. X{
  767. X    FILE *f;
  768. X    int pid;
  769. X    register row, col;
  770. X    register struct ent **pp;
  771. X    char coldelim = DEFCOLDELIM;
  772. X
  773. X    if ((strcmp(fname, curfile) == 0) &&
  774. X    !yn_ask("Confirm that you want to destroy the data base: (y,n)"))
  775. X        return;
  776. X
  777. X    if ((f = openout(fname, &pid)) == (FILE *)0)
  778. X    {    error ("Can't create file \"%s\"", fname);
  779. X    return;
  780. X    }
  781. X
  782. X    if ( tbl_style == TBL ) {
  783. X    fprintf(f,".\\\" ** %s spreadsheet output \n.TS\n",progname);
  784. X    fprintf(f,"tab(%c);\n",coldelim);
  785. X    for (col=c0;col<=cn; col++) fprintf(f," n");
  786. X    fprintf(f, ".\n");
  787. X    }
  788. X    else if ( tbl_style == LATEX ) {
  789. X    fprintf(f,"%% ** %s spreadsheet output\n\\begin{tabular}{",progname);
  790. X    for (col=c0;col<=cn; col++) fprintf(f,"c");
  791. X    fprintf(f, "}\n");
  792. X    coldelim = '&';
  793. X    }
  794. X    else if ( tbl_style == TEX ) {
  795. X    fprintf(f,"{\t%% ** %s spreadsheet output\n\\settabs %d \\columns\n",
  796. X        progname, cn-c0+1);
  797. X    coldelim = '&';
  798. X    }
  799. X
  800. X    for (row=r0; row<=rn; row++) {
  801. X    if ( tbl_style == TEX )
  802. X        (void) fprintf (f, "\\+");
  803. X    
  804. X    for (pp = ATBL(tbl, row, col=c0); col<=cn; col++, pp++) {
  805. X        if (*pp) {
  806. X        char *s;
  807. X        if ((*pp)->flags&is_valid) {
  808. X            (void) fprintf (f,"%.*f",precision[col],
  809. X                (*pp)->v);
  810. X        }
  811. X        if (s = (*pp)->label) {
  812. X                (void) fprintf (f,"%s",s);
  813. X        }
  814. X        }
  815. X        if ( col < cn )
  816. X        (void) fprintf(f,"%c",coldelim);
  817. X    }
  818. X    if ( tbl_style == LATEX ) {
  819. X        if ( row < rn ) (void) fprintf (f, "\\\\");
  820. X        }
  821. X    else if ( tbl_style == TEX ) {
  822. X        (void) fprintf (f, "\\cr");
  823. X        }
  824. X    (void) fprintf (f,"\n");
  825. X    }
  826. X
  827. X    if ( tbl_style == TBL )
  828. X    (void) fprintf (f,".TE\n.\\\" ** end of %s spreadsheet output\n", progname);
  829. X    else if ( tbl_style == LATEX )
  830. X    (void) fprintf (f,"\\end{tabular}\n%% ** end of %s spreadsheet output\n", progname);
  831. X    else if ( tbl_style == TEX )
  832. X    (void) fprintf (f,"}\n%% ** end of %s spreadsheet output\n", progname);
  833. X
  834. X    closeout(f, pid);
  835. X}
  836. X
  837. Xstruct enode *
  838. Xcopye (e, Rdelta, Cdelta)
  839. Xregister struct enode *e;
  840. Xint Rdelta, Cdelta;
  841. X{
  842. X    register struct enode *ret;
  843. X
  844. X    if (e == (struct enode *)0) {
  845. X        ret = (struct enode *)0;
  846. X    } else if (e->op & REDUCE) {
  847. X    int newrow, newcol;
  848. X    ret = (struct enode *) xmalloc ((unsigned) sizeof (struct enode));
  849. X    ret->op = e->op;
  850. X    newrow=e->e.r.left.vf & FIX_ROW ? e->e.r.left.vp->row :
  851. X                      e->e.r.left.vp->row+Rdelta;
  852. X    newcol=e->e.r.left.vf & FIX_COL ? e->e.r.left.vp->col :
  853. X                      e->e.r.left.vp->col+Cdelta;
  854. X    ret->e.r.left.vp = lookat (newrow, newcol);
  855. X    ret->e.r.left.vf = e->e.r.left.vf;
  856. X    newrow=e->e.r.right.vf & FIX_ROW ? e->e.r.right.vp->row :
  857. X                       e->e.r.right.vp->row+Rdelta;
  858. X    newcol=e->e.r.right.vf & FIX_COL ? e->e.r.right.vp->col :
  859. X                       e->e.r.right.vp->col+Cdelta;
  860. X    ret->e.r.right.vp = lookat (newrow, newcol);
  861. X    ret->e.r.right.vf = e->e.r.right.vf;
  862. X    } else {
  863. X    ret = (struct enode *) xmalloc ((unsigned) sizeof (struct enode));
  864. X    ret->op = e->op;
  865. X    switch (ret->op) {
  866. X    case 'v':
  867. X        {
  868. X            int newrow, newcol;
  869. X            newrow=e->e.v.vf & FIX_ROW ? e->e.v.vp->row :
  870. X                         e->e.v.vp->row+Rdelta;
  871. X            newcol=e->e.v.vf & FIX_COL ? e->e.v.vp->col :
  872. X                         e->e.v.vp->col+Cdelta;
  873. X            ret->e.v.vp = lookat (newrow, newcol);
  874. X            ret->e.v.vf = e->e.v.vf;
  875. X            break;
  876. X        }
  877. X    case 'k':
  878. X        ret->e.k = e->e.k;
  879. X        break;
  880. X    case 'f':
  881. X        ret->e.o.right = copye (e->e.o.right,0,0);
  882. X        ret->e.o.left = (struct enode *)0;
  883. X         break;
  884. X    case '$':
  885. X        ret->e.s = xmalloc((unsigned) strlen(e->e.s)+1);
  886. X        (void) strcpy(ret->e.s, e->e.s);
  887. X        break;
  888. X    default:
  889. X        ret->e.o.right = copye (e->e.o.right,Rdelta,Cdelta);
  890. X        ret->e.o.left = copye (e->e.o.left,Rdelta,Cdelta);
  891. X        break;
  892. X    }
  893. X    }
  894. X    return ret;
  895. X}
  896. X
  897. X/*
  898. X * sync_refs and syncref are used to remove references to
  899. X * deleted struct ents.  Note that the deleted structure must still
  900. X * be hanging around before the call, but not referenced by an entry
  901. X * in tbl.  Thus the free_ent, fix_ent calls in sc.c
  902. X */
  903. Xvoid
  904. Xsync_refs ()
  905. X{
  906. X    register i,j;
  907. X    register struct ent *p;
  908. X    sync_ranges();
  909. X    for (i=0; i<=maxrow; i++)
  910. X    for (j=0; j<=maxcol; j++)
  911. X        if ((p = *ATBL(tbl, i, j)) && p->expr)
  912. X        syncref(p->expr);
  913. X}
  914. X
  915. Xvoid
  916. Xsyncref(e)
  917. Xregister struct enode *e;
  918. X{
  919. X    if (e == (struct enode *)0)
  920. X    return;
  921. X    else if (e->op & REDUCE) {
  922. X     e->e.r.right.vp = lookat(e->e.r.right.vp->row, e->e.r.right.vp->col);
  923. X     e->e.r.left.vp = lookat(e->e.r.left.vp->row, e->e.r.left.vp->col);
  924. X    } else {
  925. X    switch (e->op) {
  926. X    case 'v':
  927. X        e->e.v.vp = lookat(e->e.v.vp->row, e->e.v.vp->col);
  928. X        break;
  929. X    case 'k':
  930. X        break;
  931. X    case '$':
  932. X        break;
  933. X    default:
  934. X        syncref(e->e.o.right);
  935. X        syncref(e->e.o.left);
  936. X        break;
  937. X    }
  938. X    }
  939. X}
  940. X
  941. Xvoid
  942. Xhiderow(arg)
  943. Xint arg;
  944. X{
  945. X    register int r1;
  946. X    register int r2;
  947. X
  948. X    r1 = currow;
  949. X    r2 = r1 + arg - 1;
  950. X    if (r1 < 0 || r1 > r2) {
  951. X    error ("Invalid range");
  952. X    return;
  953. X    }
  954. X    if (r2 >= maxrows-1)
  955. X    {    if (!growtbl(GROWROW, arg+1, 0))
  956. X    {    error("You can't hide the last row");
  957. X        return;
  958. X    }
  959. X    }
  960. X    FullUpdate++;
  961. X    modflg++;
  962. X    while (r1 <= r2)
  963. X    row_hidden[r1++] = 1;
  964. X}
  965. X
  966. Xvoid
  967. Xhidecol(arg)
  968. Xint arg;
  969. X{
  970. X    register int c1;
  971. X    register int c2;
  972. X
  973. X    c1 = curcol;
  974. X    c2 = c1 + arg - 1;
  975. X    if (c1 < 0 || c1 > c2) {
  976. X    error ("Invalid range");
  977. X    return;
  978. X    }
  979. X    if (c2 >= maxcols-1)
  980. X    {    if ((arg >= ABSMAXCOLS-1) || !growtbl(GROWCOL, 0, arg+1))
  981. X    {    error("You can't hide the last col");
  982. X        return;
  983. X    }
  984. X    }
  985. X    FullUpdate++;
  986. X    modflg++;
  987. X    while (c1 <= c2)
  988. X    col_hidden[c1++] = 1;
  989. X}
  990. X
  991. Xvoid
  992. Xshowrow(r1, r2)
  993. Xint r1, r2;
  994. X{
  995. X    if (r1 < 0 || r1 > r2) {
  996. X    error ("Invalid range");
  997. X    return;
  998. X    }
  999. X    if (r2 > maxrows-1) {
  1000. X    r2 = maxrows-1;
  1001. X    }
  1002. X    FullUpdate++;
  1003. X    modflg++;
  1004. X    while (r1 <= r2)
  1005. X    row_hidden[r1++] = 0;
  1006. X}
  1007. X
  1008. Xvoid
  1009. Xshowcol(c1, c2)
  1010. Xint c1, c2;
  1011. X{
  1012. X    if (c1 < 0 || c1 > c2) {
  1013. X    error ("Invalid range");
  1014. X    return;
  1015. X    }
  1016. X    if (c2 > maxcols-1) {
  1017. X    c2 = maxcols-1;
  1018. X    }
  1019. X    FullUpdate++;
  1020. X    modflg++;
  1021. X    while (c1 <= c2)
  1022. X    col_hidden[c1++] = 0;
  1023. X}
  1024. X
  1025. X/* Open the output file, setting up a pipe if needed */
  1026. X
  1027. XFILE *
  1028. Xopenout(fname, rpid)
  1029. Xchar *fname;
  1030. Xint *rpid;
  1031. X{
  1032. X    int pipefd[2];
  1033. X    int pid;
  1034. X    FILE *f;
  1035. X    char *efname;
  1036. X
  1037. X    while (*fname && (*fname == ' '))  /* Skip leading blanks */
  1038. X    fname++;
  1039. X
  1040. X    if (*fname != '|') {        /* Open file if not pipe */
  1041. X    *rpid = 0;
  1042. X    
  1043. X    efname = findhome(fname);
  1044. X#ifdef DOBACKUPS
  1045. X    if (!backup_file(efname) &&
  1046. X        (yn_ask("Could not create backup copy, Save anyhow?: (y,n)") != 1))
  1047. X        return(0);
  1048. X#endif
  1049. X    return(fopen(efname, "w"));
  1050. X    }
  1051. X
  1052. X    fname++;                /* Skip | */
  1053. X    if ( pipe (pipefd) < 0) {
  1054. X    error("Can't make pipe to child");
  1055. X    *rpid = 0;
  1056. X    return(0);
  1057. X    }
  1058. X
  1059. X    deraw();
  1060. X#ifdef VMS
  1061. X    fprintf(stderr, "No son tasks available yet under VMS--sorry\n");
  1062. X#else /* VMS */
  1063. X
  1064. X    if ((pid=fork()) == 0)              /* if child  */
  1065. X    {
  1066. X    (void) close (0);              /* close stdin */
  1067. X    (void) close (pipefd[1]);
  1068. X    (void) dup (pipefd[0]);          /* connect to pipe input */
  1069. X    (void) signal (SIGINT, SIG_DFL);      /* reset */
  1070. X    (void) execl ("/bin/sh", "sh", "-c", fname, 0);
  1071. X    exit (-127);
  1072. X    }
  1073. X    else                  /* else parent */
  1074. X    {
  1075. X    *rpid = pid;
  1076. X    if ((f = fdopen (pipefd[1], "w")) == (FILE *)0)
  1077. X    {
  1078. X        (void) kill (pid, -9);
  1079. X        error ("Can't fdopen output");
  1080. X        (void) close (pipefd[1]);
  1081. X        *rpid = 0;
  1082. X        return(0);
  1083. X    }
  1084. X    }
  1085. X#endif /* VMS */
  1086. X    return(f);
  1087. X}
  1088. X
  1089. Xvoid
  1090. Xcloseout(f, pid)
  1091. XFILE *f;
  1092. Xint pid;
  1093. X{
  1094. X    int temp;
  1095. X
  1096. X    (void) fclose (f);
  1097. X    if (pid) {
  1098. X         while (pid != wait(&temp)) /**/;
  1099. X     (void) printf("Press RETURN to continue ");
  1100. X     (void) fflush(stdout);
  1101. X     (void) nmgetch();
  1102. X     goraw();
  1103. X    }
  1104. X}
  1105. X
  1106. Xvoid
  1107. Xcopyent(n,p,dr,dc)
  1108. X        register struct ent *n, *p;
  1109. X        int dr, dc;
  1110. X{
  1111. X    if(!n||!p){error("internal error");return;}
  1112. X    n -> v = p -> v;
  1113. X    n -> flags = p -> flags;
  1114. X    n -> expr = copye (p -> expr, dr, dc);
  1115. X    n -> label = (char *)0;
  1116. X    if (p -> label) {
  1117. X    n -> label = (char *)
  1118. X        xmalloc  ((unsigned) (strlen (p -> label) + 1));
  1119. X    (void) strcpy (n -> label, p -> label);
  1120. X    }
  1121. X}
  1122. X
  1123. Xvoid
  1124. Xwrite_fd (f, r0, c0, rn, cn)
  1125. Xregister FILE *f;
  1126. Xint r0, c0, rn, cn;
  1127. X{
  1128. X    register struct ent **pp;
  1129. X    register r, c;
  1130. X
  1131. X    (void) fprintf (f, "# This data file was generated by the Spreadsheet ");
  1132. X    (void) fprintf (f, "Calculator.\n");
  1133. X    (void) fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
  1134. X    print_options(f);
  1135. X    for (c=0; c<maxcols; c++)
  1136. X    if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC)
  1137. X        (void) fprintf (f, "format %s %d %d\n",coltoa(c),fwidth[c],precision[c]);
  1138. X    for (c=c0; c<cn; c++) {
  1139. X        if (col_hidden[c]) {
  1140. X            (void) fprintf(f, "hide %s\n", coltoa(c));
  1141. X        }
  1142. X    }
  1143. X    for (r=r0; r<=rn; r++) {
  1144. X    if (row_hidden[r]) {
  1145. X        (void) fprintf(f, "hide %d\n", r);
  1146. X    }
  1147. X    }
  1148. X
  1149. X    write_range(f);
  1150. X
  1151. X    if (mdir) 
  1152. X        (void) fprintf(f, "mdir \"%s\"\n", mdir);
  1153. X    for (r=r0; r<=rn; r++) {
  1154. X    pp = ATBL(tbl, r, c0);
  1155. X    for (c=c0; c<=cn; c++, pp++)
  1156. X        if (*pp) {
  1157. X        if ((*pp)->label) {
  1158. X            edits(r,c);
  1159. X            (void) fprintf(f, "%s\n",line);
  1160. X        }
  1161. X        if ((*pp)->flags&is_valid) {
  1162. X            editv (r, c);
  1163. X            (void) fprintf (f, "%s\n",line);
  1164. X        }
  1165. X        }
  1166. X    }
  1167. X}
  1168. X
  1169. Xint
  1170. Xwritefile (fname, r0, c0, rn, cn)
  1171. Xchar *fname;
  1172. Xint r0, c0, rn, cn;
  1173. X{
  1174. X    register FILE *f;
  1175. X    char save[PATHLEN];
  1176. X    int pid;
  1177. X
  1178. X#ifndef VMS
  1179. X    if (Crypt) {
  1180. X    return (cwritefile(fname, r0, c0, rn, cn));
  1181. X    }
  1182. X#endif /* VMS */
  1183. X
  1184. X    if (*fname == '\0') fname = curfile;
  1185. X
  1186. X    (void) strcpy(save,fname);
  1187. X
  1188. X    if ((f= openout(fname, &pid)) == (FILE *)0)
  1189. X    {    error ("Can't create file \"%s\"", fname);
  1190. X    return (-1);
  1191. X    }
  1192. X
  1193. X    write_fd(f, r0, c0, rn, cn);
  1194. X    
  1195. X    closeout(f, pid);
  1196. X
  1197. X    if (!pid) {
  1198. X        (void) strcpy(curfile, save);
  1199. X        modflg = 0;
  1200. X        error("File \"%s\" written.",curfile);
  1201. X    }
  1202. X
  1203. X    return (0);
  1204. X}
  1205. X
  1206. Xvoid
  1207. Xreadfile (fname,eraseflg)
  1208. Xchar *fname;
  1209. Xint eraseflg;
  1210. X{
  1211. X    register FILE *f;
  1212. X    char save[PATHLEN];
  1213. X
  1214. X    if (*fname == '*' && mdir) { 
  1215. X       (void) strcpy(save, mdir);
  1216. X       *fname = '/';
  1217. X       (void) strcat(save, fname);
  1218. X    } else {
  1219. X        if (*fname == '\0')
  1220. X        fname = curfile;
  1221. X        (void) strcpy(save,fname);
  1222. X    }
  1223. X
  1224. X#ifndef VMS
  1225. X    if (Crypt)  {
  1226. X    creadfile(save, eraseflg);
  1227. X    return;
  1228. X    }
  1229. X#endif /* VMS */
  1230. X
  1231. X    if (eraseflg && strcmp(fname,curfile) && modcheck(" first")) return;
  1232. X
  1233. X    if ((f = fopen(findhome(save), "r")) == (FILE *)0)
  1234. X    {    error ("Can't read file \"%s\"", save);
  1235. X    return;
  1236. X    }
  1237. X
  1238. X    if (eraseflg) erasedb ();
  1239. X
  1240. X    loading++;
  1241. X    while (fgets(line,sizeof line,f)) {
  1242. X    linelim = 0;
  1243. X    if (line[0] != '#') (void) yyparse ();
  1244. X    }
  1245. X    --loading;
  1246. X    (void) fclose (f);
  1247. X    linelim = -1;
  1248. X    modflg++;
  1249. X    if (eraseflg) {
  1250. X    (void) strcpy(curfile,save);
  1251. X    modflg = 0;
  1252. X    }
  1253. X    EvalAll();
  1254. X}
  1255. X
  1256. Xvoid
  1257. Xerasedb ()
  1258. X{
  1259. X    register r, c;
  1260. X    for (c = 0; c<=maxcol; c++) {
  1261. X    fwidth[c] = DEFWIDTH;
  1262. X    precision[c] = DEFPREC;
  1263. X    }
  1264. X
  1265. X    for (r = 0; r<=maxrow; r++) {
  1266. X    register struct ent **pp = ATBL(tbl, r, 0);
  1267. X    for (c=0; c++<=maxcol; pp++)
  1268. X        if (*pp) {
  1269. X        if ((*pp)->expr) efree (*pp, (*pp) -> expr);
  1270. X        if ((*pp)->label) xfree ((char *)((*pp) -> label));
  1271. X        xfree ((char *)(*pp));
  1272. X        *pp = (struct ent *)0;
  1273. X        }
  1274. X    }
  1275. X    maxrow = 0;
  1276. X    maxcol = 0;
  1277. X    clean_range();
  1278. X    FullUpdate++;
  1279. X}
  1280. X
  1281. Xvoid
  1282. Xbackcol(arg)
  1283. X    int arg;
  1284. X{
  1285. X    while (--arg>=0) {
  1286. X    if (curcol)
  1287. X        curcol--;
  1288. X    else
  1289. X        {error ("At column A"); break;}
  1290. X    while(col_hidden[curcol] && curcol)
  1291. X        curcol--;
  1292. X    }
  1293. X}
  1294. X
  1295. Xvoid
  1296. Xforwcol(arg)
  1297. X    int arg;
  1298. X{
  1299. X    while (--arg>=0) {
  1300. X    if (curcol < maxcols - 1)
  1301. X        curcol++;
  1302. X    else
  1303. X    if (!growtbl(GROWCOL, 0, arg))    /* get as much as needed */
  1304. X        break;
  1305. X    while(col_hidden[curcol]&&(curcol<maxcols-1))
  1306. X        curcol++;
  1307. X    }
  1308. X}
  1309. X
  1310. Xvoid
  1311. Xforwrow(arg)
  1312. X    int arg;
  1313. X{
  1314. X    while (--arg>=0) {
  1315. X    if (currow < maxrows - 1)
  1316. X        currow++;
  1317. X    else
  1318. X    if (!growtbl(GROWROW, arg, 0))    /* get as much as needed */
  1319. X        break;
  1320. X    while (row_hidden[currow]&&(currow<maxrows-1))
  1321. X        currow++;
  1322. X    }
  1323. X}
  1324. X
  1325. Xvoid
  1326. Xbackrow(arg)
  1327. X    int arg;
  1328. X{
  1329. X    while (--arg>=0) {
  1330. X    if (currow)
  1331. X        currow--;
  1332. X    else
  1333. X        {error ("At row zero"); break;}
  1334. X    while (row_hidden[currow] && currow)
  1335. X        currow--;
  1336. X    }
  1337. X}
  1338. X
  1339. X
  1340. X/*
  1341. X * Show a cell's label string or expression value.  May overwrite value if
  1342. X * there is one already displayed in the cell.  Created from old code in
  1343. X * update(), copied with minimal changes.
  1344. X */
  1345. X
  1346. Xvoid
  1347. Xshowstring (string, leftflush, hasvalue, row, col, nextcolp, mxcol, fieldlenp, r, c)
  1348. X    char *string;    /* to display */
  1349. X    int leftflush;    /* or rightflush */
  1350. X    int hasvalue;    /* is there a numeric value? */
  1351. X    int row, col;    /* spreadsheet location */
  1352. X    int *nextcolp;    /* value returned through it */
  1353. X    int mxcol;        /* last column displayed? */
  1354. X    int *fieldlenp;    /* value returned through it */
  1355. X    int r, c;        /* screen row and column */
  1356. X{
  1357. X    register int nextcol  = *nextcolp;
  1358. X    register int fieldlen = *fieldlenp;
  1359. X
  1360. X    char field[FBUFLEN];
  1361. X    int  slen;
  1362. X    char *start, *last;
  1363. X    register char *fp;
  1364. X    struct ent *nc;
  1365. X
  1366. X    /* This figures out if the label is allowed to
  1367. X       slop over into the next blank field */
  1368. X
  1369. X    slen = strlen (string);
  1370. X    while ((slen > fieldlen) && (nextcol <= mxcol) &&
  1371. X       !((nc = lookat (row, nextcol)) -> flags & is_valid) &&
  1372. X       !(nc->label)) {
  1373. X
  1374. X    if (! col_hidden [nextcol])
  1375. X        fieldlen += fwidth [nextcol];
  1376. X
  1377. X    nextcol++;
  1378. X    }
  1379. X    if (slen > fieldlen)
  1380. X    slen = fieldlen;
  1381. X
  1382. X    /* Now justify and print */
  1383. X    start = leftflush ? field : field + fieldlen - slen;
  1384. X    last = field+fieldlen;
  1385. X    fp = field;
  1386. X    while (fp < start)
  1387. X    *fp++ = ' ';
  1388. X    while (slen--)
  1389. X    *fp++ = *string++;
  1390. X    if ((! hasvalue) || fieldlen != fwidth[col]) 
  1391. X    while (fp < last)
  1392. X        *fp++ = ' ';
  1393. X    *fp = '\0';
  1394. X#ifdef VMS
  1395. X    mvaddstr(r, c, field);    /* this is a macro */
  1396. X#else
  1397. X    (void) mvaddstr(r, c, field);
  1398. X#endif
  1399. X
  1400. X    *nextcolp  = nextcol;
  1401. X    *fieldlenp = fieldlen;
  1402. X}
  1403. X
  1404. Xint
  1405. Xetype(e)
  1406. Xregister struct enode *e;
  1407. X{
  1408. X    if (e == (struct enode *)0)
  1409. X    return NUM;
  1410. X    switch (e->op) {
  1411. X    case O_SCONST: case '#': case DATE: case FMT: case STINDEX:
  1412. X    case EXT: case SVAL: case SUBSTR:
  1413. X        return (STR);
  1414. X
  1415. X    case '?':
  1416. X    case IF:
  1417. X        return(etype(e->e.o.right->e.o.left));
  1418. X
  1419. X    case 'f':
  1420. X        return(etype(e->e.o.right));
  1421. X
  1422. X    case O_VAR: {
  1423. X    register struct ent *p;
  1424. X    p = e->e.v.vp;
  1425. X    if (p->expr) 
  1426. X        return(p->flags & is_strexpr ? STR : NUM);
  1427. X    else if (p->label)
  1428. X        return(STR);
  1429. X    else
  1430. X        return(NUM);
  1431. X    }
  1432. X
  1433. X    default:
  1434. X    return(NUM);
  1435. X    }
  1436. X}
  1437. X
  1438. X/* return 1 if yes given, 0 otherwise */
  1439. Xint
  1440. Xyn_ask(msg)
  1441. Xchar    *msg;
  1442. X{    char ch;
  1443. X
  1444. X    (void) move (0, 0);
  1445. X    (void) clrtoeol ();
  1446. X    (void) addstr (msg);
  1447. X    (void) refresh();
  1448. X    ch = nmgetch();
  1449. X    if ( ch != 'y' && ch != 'Y' && ch != 'n' && ch != 'N' ) {
  1450. X        if (ch == ctl('g') || ch == ESC)
  1451. X            return(-1);
  1452. X        error("y or n response required");
  1453. X        return (-1);
  1454. X    }
  1455. X    if (ch == 'y' || ch == 'Y')
  1456. X        return(1);
  1457. X    else
  1458. X        return(0);
  1459. X}
  1460. X
  1461. X#include <pwd.h>
  1462. Xchar    *
  1463. Xfindhome(path)
  1464. Xchar    *path;
  1465. X{
  1466. X    static    char    *HomeDir = NULL;
  1467. X    extern    char    *getenv();
  1468. X
  1469. X    if (*path == '~')
  1470. X    {    char    *pathptr;
  1471. X        char    tmppath[PATHLEN];
  1472. X
  1473. X        if (HomeDir == NULL)
  1474. X        {    HomeDir = getenv("HOME");
  1475. X            if (HomeDir == NULL)
  1476. X                HomeDir = "/";
  1477. X        }
  1478. X        pathptr = path + 1;
  1479. X        if ((*pathptr == '/') || (*pathptr == '\0'))
  1480. X        {    strcpy(tmppath, HomeDir);
  1481. X        }
  1482. X        else
  1483. X        {    struct    passwd *pwent;
  1484. X            extern    struct    passwd *getpwnam();
  1485. X            char    *namep;
  1486. X            char    name[50];
  1487. X
  1488. X            namep = name;
  1489. X            while ((*pathptr != '\0') && (*pathptr != '/'))
  1490. X                *(namep++) = *(pathptr++);
  1491. X            *namep = '\0';
  1492. X            if ((pwent = getpwnam(name)) == NULL)
  1493. X            {    sprintf(path, "Can't find user %s", name);
  1494. X                return(NULL);
  1495. X            }
  1496. X            strcpy(tmppath, pwent->pw_dir);
  1497. X        }
  1498. X
  1499. X        strcat(tmppath, pathptr);
  1500. X        strcpy(path, tmppath);
  1501. X    }
  1502. X    return(path);
  1503. X}
  1504. X
  1505. X#ifdef DOBACKUPS
  1506. X#include <sys/types.h>
  1507. X#include <sys/stat.h>
  1508. X
  1509. X/*
  1510. X * make a backup copy of a file, use the same mode and name in the format
  1511. X * [path/]#file~
  1512. X * return 1 if we were successful, 0 otherwise
  1513. X */
  1514. Xint
  1515. Xbackup_file(path)
  1516. Xchar    *path;
  1517. X{
  1518. X    struct    stat    statbuf;
  1519. X    char    fname[PATHLEN];
  1520. X    char    tpath[PATHLEN];
  1521. X#ifdef sequent
  1522. X    char    *buf;
  1523. X#else
  1524. X    char    buf[BUFSIZ];
  1525. X#endif
  1526. X    char    *tpp;
  1527. X    int    infd, outfd;
  1528. X    int    count;
  1529. X
  1530. X    /* tpath will be the [path/]file ---> [path/]#file~ */
  1531. X    strcpy(tpath, path);
  1532. X    if ((tpp = strrchr(tpath, '/')) == NULL)
  1533. X        tpp = tpath;
  1534. X    else
  1535. X        tpp++;
  1536. X    strcpy(fname, tpp);
  1537. X    sprintf(tpp, "#%s~", fname);
  1538. X
  1539. X    if (stat(path, &statbuf) == 0)
  1540. X    {
  1541. X#ifdef sequent
  1542. X        if ((buf = xmalloc(statbuf.st_blksize)) == (char *)0)
  1543. X            return(0);
  1544. X#endif
  1545. X
  1546. X        if ((infd = open(path, O_RDONLY, 0)) < 0)
  1547. X        {
  1548. X#ifdef sequent
  1549. X            xfree(buf);
  1550. X#endif
  1551. X            return(0);
  1552. X        }
  1553. X        if ((outfd = open(tpath, O_TRUNC|O_WRONLY|O_CREAT,
  1554. X                    statbuf.st_mode)) < 0)
  1555. X        {
  1556. X#ifdef sequent
  1557. X            xfree(buf);
  1558. X#endif
  1559. X            return(0);
  1560. X        }
  1561. X#ifdef sequent
  1562. X        while((count = read(infd, buf, statbuf.st_blksize)) > 0)
  1563. X#else
  1564. X        while((count = read(infd, buf, sizeof(buf))) > 0)
  1565. X#endif
  1566. X        {    if (write(outfd, buf, count) != count)
  1567. X            {    count = -1;
  1568. X                break;
  1569. X            }
  1570. X        }
  1571. X        close(infd);
  1572. X        close(outfd);
  1573. X#ifdef sequent
  1574. X        xfree(buf);
  1575. X#endif
  1576. X        return((count < 0) ? 0 : 1);
  1577. X    }
  1578. X    else
  1579. X    if (errno == ENOENT)
  1580. X        return(1);
  1581. X    return(0);
  1582. X}
  1583. X#endif
  1584. END_OF_FILE
  1585.   if test 30867 -ne `wc -c <'cmds.c'`; then
  1586.     echo shar: \"'cmds.c'\" unpacked with wrong size!
  1587.   fi
  1588.   # end of 'cmds.c'
  1589. fi
  1590. if test -f 'lex.c' -a "${1}" != "-c" ; then 
  1591.   echo shar: Will not clobber existing file \"'lex.c'\"
  1592. else
  1593.   echo shar: Extracting \"'lex.c'\" \(13128 characters\)
  1594.   sed "s/^X//" >'lex.c' <<'END_OF_FILE'
  1595. X/*    SC    A Spreadsheet Calculator
  1596. X *        Lexical analyser
  1597. X *
  1598. X *        original by James Gosling, September 1982
  1599. X *        modifications by Mark Weiser and Bruce Israel,
  1600. X *            University of Maryland
  1601. X *
  1602. X *              More mods Robert Bond, 12/86
  1603. X *        More mods by Alan Silverstein, 3/88, see list of changes.
  1604. X *        $Revision: 6.8 $
  1605. X *
  1606. X */
  1607. X
  1608. X
  1609. X
  1610. X#if defined(BSD42) || defined(BSD43)
  1611. X#include <sys/ioctl.h>
  1612. X#endif 
  1613. X
  1614. X#ifdef IEEE_MATH
  1615. X#include <ieeefp.h>
  1616. X#endif /* IEEE_MATH */
  1617. X
  1618. X#include <curses.h>
  1619. X#include <signal.h>
  1620. X#include <setjmp.h>
  1621. X#include "sc.h"
  1622. X#include <ctype.h>
  1623. X
  1624. X#ifdef BSD42
  1625. X#include <strings.h>
  1626. X#else
  1627. X#ifndef SYSIII
  1628. X#include <string.h>
  1629. X#endif
  1630. X#endif
  1631. X
  1632. X#ifdef VMS
  1633. X#include "gram_tab.h"
  1634. Xtypedef union {
  1635. X    int ival;
  1636. X    double fval;
  1637. X    struct ent *ent;
  1638. X    struct enode *enode;
  1639. X    char *sval;
  1640. X    struct range_s rval;
  1641. X} YYSTYPE;
  1642. Xextern YYSTYPE yylval;
  1643. Xextern int VMS_read_raw;   /*sigh*/
  1644. X#else    /* VMS */
  1645. X#include "y.tab.h"
  1646. X#endif /* VMS */
  1647. X
  1648. Xchar *strtof();
  1649. X
  1650. Xjmp_buf wakeup;
  1651. Xjmp_buf fpe_buf;
  1652. X
  1653. Xstruct key {
  1654. X    char *key;
  1655. X    int val;
  1656. X};
  1657. X
  1658. Xstruct key experres[] = {
  1659. X#include "experres.h"
  1660. X    0, 0};
  1661. X
  1662. Xstruct key statres[] = {
  1663. X#include "statres.h"
  1664. X    0, 0};
  1665. X
  1666. Xyylex ()
  1667. X{
  1668. X    register char *p = line+linelim;
  1669. X    int ret;
  1670. X    while (isspace(*p)) p++;
  1671. X    if (*p == '\0') ret = -1;
  1672. X    else if (isalpha(*p)) {
  1673. X    char *tokenst = p;
  1674. X    register tokenl;
  1675. X    register struct key *tblp;
  1676. X    tokenl = 0;
  1677. X    /*
  1678. X     * This picks up either 1 or 2 alpha characters (a column) or
  1679. X     * tokens with at least three leading alphas and '_' or digits
  1680. X     * (a function or token or command or a range name)
  1681. X    */
  1682. X    while (isalpha(*p) || ((*p == '_') || isdigit(*p)) && (tokenl > 2)) {
  1683. X        p++;
  1684. X        tokenl++;
  1685. X    }
  1686. X    if (tokenl <= 2) { /* a COL is 1 or 2 char alpha
  1687. X        (but not pi, ln, fv, pv, if -- this should be fixed!) */
  1688. X        if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'i') {
  1689. X        ret = K_PI;
  1690. X        } else if (tokenl == 2 && tokenst[0] == 'l' && tokenst[1] == 'n') {
  1691. X        ret = K_LN;
  1692. X        } else if (tokenl == 2 && tokenst[0] == 'f' && tokenst[1] == 'v') {
  1693. X        ret = K_FV;
  1694. X        } else if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'v') {
  1695. X        ret = K_PV;
  1696. X        } else if (tokenl == 2 && tokenst[0] == 'i' && tokenst[1] == 'f') {
  1697. X        ret = K_IF;
  1698. X
  1699. X        } else {
  1700. X        ret = COL;
  1701. X        yylval.ival = atocol (tokenst, tokenl);
  1702. X        }
  1703. X    } else {
  1704. X        ret = WORD;
  1705. X        for (tblp = linelim ? experres : statres; tblp->key; tblp++)
  1706. X            if (((tblp->key[0]^tokenst[0])&0137)==0
  1707. X             && tblp->key[tokenl]==0) {
  1708. X            register i = 1;
  1709. X            while (i<tokenl && ((tokenst[i]^tblp->key[i])&0137)==0)
  1710. X                i++;
  1711. X            if (i>=tokenl) {
  1712. X                ret = tblp->val;
  1713. X                break;
  1714. X            }
  1715. X            }
  1716. X        if (ret==WORD) { 
  1717. X        struct range *r;
  1718. X        if (r = find_range(tokenst, tokenl,
  1719. X                   (struct ent *)0, (struct ent *)0)) {
  1720. X            yylval.rval.left = r->r_left;
  1721. X            yylval.rval.right = r->r_right;
  1722. X            if (r->r_is_range)
  1723. X                ret = RANGE;
  1724. X            else
  1725. X            ret = VAR;
  1726. X        } else {
  1727. X            linelim = p-line;
  1728. X            yyerror ("Unintelligible word");
  1729. X        }
  1730. X        }
  1731. X    }
  1732. X    } else if ((*p == '.') || isdigit(*p)) {
  1733. X    double v = 0;
  1734. X    int temp;
  1735. X    char *nstart = p;
  1736. X    if (*p != '.') {
  1737. X        do v = v*10 + (double)(*p-'0');
  1738. X        while (isdigit(*++p));
  1739. X    }
  1740. X    if (*p=='.' || *p == 'e' || *p == 'E') {
  1741. X        ret = FNUMBER;
  1742. X        p = strtof(nstart, &yylval.fval);
  1743. X    } else {
  1744. X        /* A NUMBER must hold at least MAXROW and MAXCOL */
  1745. X        /* This is consistent with a short row and col in struct ent */
  1746. X        if (v > (double)32767 || v < (double)-32768) {
  1747. X        ret = FNUMBER;
  1748. X        yylval.fval = v;
  1749. X        } else {
  1750. X        temp = (int)v;
  1751. X        if((double)temp != v) {
  1752. X            ret = FNUMBER;
  1753. X            yylval.fval = v;
  1754. X        } else {
  1755. X            ret = NUMBER;
  1756. X            yylval.ival = temp;
  1757. X        }
  1758. X        }
  1759. X    }
  1760. X    } else if (*p=='"') {
  1761. X    char *ptr;
  1762. X        ptr = p+1;
  1763. X        while(*ptr && *ptr++ != '"');
  1764. X        ptr = xmalloc((unsigned)(ptr-p));
  1765. X    yylval.sval = ptr;
  1766. X    p += 1;
  1767. X    while (*p && *p!='"') *ptr++ = *p++;
  1768. X    *ptr = 0;
  1769. X    if (*p) p += 1;
  1770. X    ret = STRING;
  1771. X    } else if (*p=='[') {
  1772. X    while (*p && *p!=']') p++;
  1773. X    if (*p) p++;
  1774. X    linelim = p-line;
  1775. X    return yylex();
  1776. X    } else ret = *p++;
  1777. X    linelim = p-line;
  1778. X    return ret;
  1779. X}
  1780. X
  1781. X
  1782. X/*
  1783. X * Given a token string starting with a symbolic column name and its valid
  1784. X * length, convert column name ("A"-"Z" or "AA"-"ZZ") to a column number (0-N).
  1785. X * Never mind if the column number is illegal (too high).  The procedure's name
  1786. X * and function are the inverse of coltoa().
  1787. X * 
  1788. X * Case-insensitivity is done crudely, by ignoring the 040 bit.
  1789. X */
  1790. X
  1791. Xint
  1792. Xatocol (string, len)
  1793. X    char    *string;
  1794. X    int    len;
  1795. X{
  1796. X    register int col;
  1797. X
  1798. X    col = (string [0] & 0137) - 'A';
  1799. X
  1800. X    if (len == 2)        /* has second char */
  1801. X        col = ((col + 1) * 26) + ((string [1] & 0137) - 'A');
  1802. X
  1803. X    return (col);
  1804. X}
  1805. X
  1806. X
  1807. X#ifdef SIMPLE
  1808. X
  1809. Xinitkbd()
  1810. X{}
  1811. X
  1812. Xkbd_again()
  1813. X{}
  1814. X
  1815. Xresetkbd()
  1816. X{}
  1817. X
  1818. X#ifndef VMS
  1819. X
  1820. Xnmgetch()
  1821. X{
  1822. X    return (toascii(getchar()));
  1823. X}
  1824. X
  1825. X#else /* VMS */
  1826. X
  1827. Xnmgetch()
  1828. X/*
  1829. X   This is not perfect, it doesn't move the cursor when goraw changes
  1830. X   over to deraw, but it works well enough since the whole sc package
  1831. X   is incredibly stable (loop constantly positions cursor).
  1832. X
  1833. X   Question, why didn't the VMS people just implement cbreak?
  1834. X
  1835. X   NOTE: During testing it was discovered that the DEBUGGER and curses
  1836. X   and this method of reading would collide (the screen was not updated
  1837. X   when continuing from screen mode in the debugger).
  1838. X*/
  1839. X{
  1840. X    short c;
  1841. X    static int key_id=0;
  1842. X    int status;
  1843. X#define VMScheck(a) {if (~(status = (a)) & 1) VMS_MSG (status);}
  1844. X
  1845. X    if (VMS_read_raw) {
  1846. X      VMScheck(smg$read_keystroke (&stdkb->_id, &c, 0, 0, 0));
  1847. X    }
  1848. X    else
  1849. X       c = getchar();
  1850. X
  1851. X    switch (c) {
  1852. X    case SMG$K_TRM_LEFT:  c = ctl('b'); break;
  1853. X    case SMG$K_TRM_RIGHT: c = ctl('f'); break;
  1854. X    case SMG$K_TRM_UP:    c = ctl('p'); break;
  1855. X    case SMG$K_TRM_DOWN:  c = ctl('n'); break;
  1856. X    default:   c = c & 0x7f;
  1857. X    }
  1858. X    return (c);
  1859. X}
  1860. X
  1861. X
  1862. XVMS_MSG (status)
  1863. Xint status;
  1864. X/*
  1865. X   Routine to put out the VMS operating system error (if one occurs).
  1866. X*/
  1867. X{
  1868. X#include <descrip.h>
  1869. X   char errstr[81], buf[120];
  1870. X   $DESCRIPTOR(errdesc, errstr);
  1871. X   short int length;
  1872. X#define err_out(msg) fprintf (stderr,msg)
  1873. X
  1874. X/* Check for no error or standard error */
  1875. X
  1876. X   if (~status & 1) {
  1877. X      status = status & 0x8000 ? status & 0xFFFFFFF : status & 0xFFFF;
  1878. X      if (SYS$GETMSG(status, &length, &errdesc, 1, 0) == SS$_NORMAL) {
  1879. X         errstr[length] = '\0';
  1880. X         sprintf (buf, "<0x%x> %s", status, errdesc.dsc$a_pointer);
  1881. X         err_out (buf);
  1882. X      }
  1883. X      else
  1884. X         err_out ("System error");
  1885. X   }
  1886. X}
  1887. X#endif /* VMS */
  1888. X
  1889. X#else /*SIMPLE*/
  1890. X
  1891. X#if defined(BSD42) || defined (SYSIII) || defined(BSD43)
  1892. X
  1893. X#define N_KEY 4
  1894. X
  1895. Xstruct key_map {
  1896. X    char *k_str;
  1897. X    char k_val;
  1898. X    char k_index;
  1899. X}; 
  1900. X
  1901. Xstruct key_map km[N_KEY];
  1902. X
  1903. Xchar keyarea[N_KEY*30];
  1904. X
  1905. Xchar *tgetstr();
  1906. Xchar *getenv();
  1907. Xchar *ks;
  1908. Xchar ks_buf[20];
  1909. Xchar *ke;
  1910. Xchar ke_buf[20];
  1911. X
  1912. X#ifdef TIOCSLTC
  1913. Xstruct ltchars old_chars, new_chars;
  1914. X#endif
  1915. X
  1916. Xchar dont_use[] = {
  1917. X    ctl('['), ctl('a'), ctl('b'), ctl('c'), ctl('e'), ctl('f'), ctl('g'), ctl('h'),
  1918. X    ctl('i'), ctl('j'),  ctl('l'), ctl('m'), ctl('n'), ctl('p'), ctl('q'),
  1919. X    ctl('r'), ctl('s'), ctl('t'), ctl('u'), ctl('v'),  ctl('w'), ctl('x'),
  1920. X    ctl('z'), 0
  1921. X};
  1922. X
  1923. Xcharout(c)
  1924. Xint c;
  1925. X{
  1926. X    (void)putchar(c);
  1927. X}
  1928. X
  1929. Xinitkbd()
  1930. X{
  1931. X    register struct key_map *kp;
  1932. X    register i,j;
  1933. X    char *p = keyarea;
  1934. X    char *ktmp;
  1935. X    static char buf[1024]; /* Why do I have to do this again? */
  1936. X
  1937. X    if (tgetent(buf, getenv("TERM")) <= 0)
  1938. X    return;
  1939. X
  1940. X    km[0].k_str = tgetstr("kl", &p); km[0].k_val = ctl('b');
  1941. X    km[1].k_str = tgetstr("kr", &p); km[1].k_val = ctl('f');
  1942. X    km[2].k_str = tgetstr("ku", &p); km[2].k_val = ctl('p');
  1943. X    km[3].k_str = tgetstr("kd", &p); km[3].k_val = ctl('n');
  1944. X    ktmp = tgetstr("ks",&p);
  1945. X    if (ktmp)  {
  1946. X    (void) strcpy(ks_buf, ktmp);
  1947. X    ks = ks_buf;
  1948. X    tputs(ks, 1, charout);
  1949. X    }
  1950. X    ktmp = tgetstr("ke",&p);
  1951. X    if (ktmp)  {
  1952. X    (void) strcpy(ke_buf, ktmp);
  1953. X    ke = ke_buf;
  1954. X    }
  1955. X
  1956. X    /* Unmap arrow keys which conflict with our ctl keys   */
  1957. X    /* Ignore unset, longer than length 1, and 1-1 mapped keys */
  1958. X
  1959. X    for (i = 0; i < N_KEY; i++) {
  1960. X    kp = &km[i];
  1961. X    if (kp->k_str && (kp->k_str[1] == 0) && (kp->k_str[0] != kp->k_val))
  1962. X        for (j = 0; dont_use[j] != 0; j++)
  1963. X            if (kp->k_str[0] == dont_use[j]) {
  1964. X             kp->k_str = (char *)0;
  1965. X             break;
  1966. X        }
  1967. X    }
  1968. X
  1969. X
  1970. X#ifdef TIOCSLTC
  1971. X    (void)ioctl(fileno(stdin), TIOCGLTC, (char *)&old_chars);
  1972. X    new_chars = old_chars;
  1973. X    if (old_chars.t_lnextc == ctl('v'))
  1974. X    new_chars.t_lnextc = -1;
  1975. X    if (old_chars.t_rprntc == ctl('r'))
  1976. X    new_chars.t_rprntc = -1;
  1977. X    (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
  1978. X#endif
  1979. X}
  1980. X
  1981. Xvoid
  1982. Xkbd_again()
  1983. X{
  1984. X    if (ks) 
  1985. X    tputs(ks, 1, charout);
  1986. X
  1987. X#ifdef TIOCSLTC
  1988. X    (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
  1989. X#endif
  1990. X}
  1991. X
  1992. Xvoid
  1993. Xresetkbd()
  1994. X{
  1995. X    if (ke) 
  1996. X    tputs(ke, 1, charout);
  1997. X
  1998. X#ifdef TIOCSLTC
  1999. X    (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&old_chars);
  2000. X#endif
  2001. X}
  2002. X
  2003. Xnmgetch() 
  2004. X{
  2005. X    register int c;
  2006. X    register struct key_map *kp;
  2007. X    register struct key_map *biggest;
  2008. X    register int i;
  2009. X    int almost;
  2010. X    int maybe;
  2011. X
  2012. X    static char dumpbuf[10];
  2013. X    static char *dumpindex;
  2014. X
  2015. X#ifdef SIGVOID
  2016. X    void time_out();
  2017. X#else
  2018. X    int time_out();
  2019. X#endif
  2020. X
  2021. X    if (dumpindex && *dumpindex)
  2022. X        return (*dumpindex++);
  2023. X
  2024. X    c = toascii(getchar());
  2025. X    biggest = 0;
  2026. X    almost = 0;
  2027. X
  2028. X    for (kp = &km[0]; kp < &km[N_KEY]; kp++) {
  2029. X    if (!kp->k_str)
  2030. X        continue;
  2031. X    if (c == kp->k_str[kp->k_index]) {
  2032. X        almost = 1;
  2033. X        kp->k_index++;
  2034. X        if (kp->k_str[kp->k_index] == 0) {
  2035. X        c = kp->k_val;
  2036. X            for (kp = &km[0]; kp < &km[N_KEY]; kp++)
  2037. X                kp->k_index = 0;
  2038. X            return(c);
  2039. X        }
  2040. X    }
  2041. X    if (!biggest && kp->k_index)
  2042. X        biggest = kp;
  2043. X        else if (kp->k_index && biggest->k_index < kp->k_index)
  2044. X        biggest = kp;
  2045. X    }
  2046. X
  2047. X    if (almost) { 
  2048. X        (void) signal(SIGALRM, time_out);
  2049. X        (void) alarm(1);
  2050. X
  2051. X    if (setjmp(wakeup) == 0) { 
  2052. X        maybe = nmgetch();
  2053. X        (void) alarm(0);
  2054. X        return(maybe);
  2055. X    }
  2056. X    }
  2057. X    
  2058. X    if (biggest) {
  2059. X    for (i = 0; i<biggest->k_index; i++) 
  2060. X        dumpbuf[i] = biggest->k_str[i];
  2061. X    if (!almost)
  2062. X        dumpbuf[i++] = c;
  2063. X    dumpbuf[i] = '\0';
  2064. X    dumpindex = &dumpbuf[1];
  2065. X    for (kp = &km[0]; kp < &km[N_KEY]; kp++)
  2066. X        kp->k_index = 0;
  2067. X    return (dumpbuf[0]);
  2068. X    }
  2069. X
  2070. X    return(c);
  2071. X}
  2072. X
  2073. X#endif
  2074. X
  2075. X#if defined(SYSV2) || defined(SYSV3)
  2076. X
  2077. Xinitkbd()
  2078. X{
  2079. X    keypad(stdscr, TRUE);
  2080. X}
  2081. X
  2082. Xvoid
  2083. Xkbd_again()
  2084. X{
  2085. X    keypad(stdscr, TRUE);
  2086. X}
  2087. X
  2088. Xvoid
  2089. Xresetkbd()
  2090. X{
  2091. X    keypad(stdscr, FALSE);
  2092. X}
  2093. X
  2094. Xnmgetch()
  2095. X{
  2096. X    register int c;
  2097. X
  2098. X    c = getch();
  2099. X    switch (c) {
  2100. X    case KEY_LEFT:  c = ctl('b'); break;
  2101. X    case KEY_RIGHT: c = ctl('f'); break;
  2102. X    case KEY_UP:    c = ctl('p'); break;
  2103. X    case KEY_DOWN:  c = ctl('n'); break;
  2104. X#ifdef KEY_C1
  2105. X/* This stuff works for a wyse wy75 in ANSI mode under 5.3.  Good luck. */
  2106. X/* It is supposed to map the curses keypad back to the numeric equiv. */
  2107. X    case KEY_C1:    c = '0'; break;
  2108. X    case KEY_A1:    c = '1'; break;
  2109. X    case KEY_B2:    c = '2'; break;
  2110. X    case KEY_A3:    c = '3'; break;
  2111. X    case KEY_F(5):  c = '4'; break;
  2112. X    case KEY_F(6):  c = '5'; break;
  2113. X    case KEY_F(7):  c = '6'; break;
  2114. X    case KEY_F(9):  c = '7'; break;
  2115. X    case KEY_F(10): c = '8'; break;
  2116. X    case KEY_F0:    c = '9'; break;
  2117. X    case KEY_C3:    c = '.'; break;
  2118. X    case KEY_ENTER: c = ctl('m'); break;
  2119. X#endif
  2120. X    default:   c = toascii(c); 
  2121. X    break;
  2122. X    }
  2123. X    return (c);
  2124. X}
  2125. X
  2126. X#endif /* SYSV2 || SYSV3 */
  2127. X
  2128. X#endif /* SIMPLE */
  2129. X
  2130. X#ifdef SIGVOID
  2131. Xvoid
  2132. X#endif
  2133. Xtime_out(signo)
  2134. Xint signo;
  2135. X{
  2136. X#ifdef IEEE_MATH
  2137. X    (void)fpsetsticky((fp_except)0);         /* Clear exception */
  2138. X#endif /* IEEE_MATH */
  2139. X    longjmp(wakeup, -1);
  2140. X}
  2141. X
  2142. X#ifdef SIGVOID
  2143. Xvoid
  2144. X#endif
  2145. Xfpe_trap(signo)
  2146. Xint signo;
  2147. X{
  2148. X    longjmp(fpe_buf, 1);
  2149. X}
  2150. X
  2151. X/*
  2152. X * This converts a floating point number of the form
  2153. X * [s]ddd[.d*][esd*]  where s can be a + or - and e is E or e.
  2154. X * to floating point. 
  2155. X * p is advanced.
  2156. X */
  2157. X
  2158. Xchar *
  2159. Xstrtof(p, res)
  2160. Xregister char *p;
  2161. Xdouble *res;
  2162. X{
  2163. X    double acc;
  2164. X    int sign;
  2165. X    double fpos;
  2166. X    int exp;
  2167. X    int exps;
  2168. X#ifdef SIGVOID
  2169. X    void (*sig_save)();
  2170. X#else
  2171. X    int (*sig_save)();
  2172. X#endif
  2173. X
  2174. X    sig_save = signal(SIGFPE, fpe_trap);
  2175. X    if (setjmp(fpe_buf)) {
  2176. X    error("Floating point exception\n");
  2177. X    *res = 0.0; 
  2178. X        (void) signal(SIGFPE, sig_save);
  2179. X    return(p);
  2180. X    }
  2181. X    acc = 0.0;
  2182. X    sign = 1;
  2183. X    exp = 0;
  2184. X    exps = 1;
  2185. X    if (*p == '+')
  2186. X        p++;
  2187. X    else if (*p == '-') {
  2188. X        p++;
  2189. X        sign = -1;
  2190. X    }
  2191. X    while (isdigit(*p)) {
  2192. X        acc = acc * 10.0 + (double)(*p - '0');
  2193. X        p++;
  2194. X    }
  2195. X    if (*p == 'e' || *p == 'E') {
  2196. X        p++;
  2197. X        if (*p == '+')
  2198. X        p++;
  2199. X        else if (*p == '-') {
  2200. X        p++;
  2201. X        exps = -1;
  2202. X        }
  2203. X        while(isdigit(*p)) {
  2204. X        exp = exp * 10 + (*p - '0');
  2205. X        p++;
  2206. X        }
  2207. X    }
  2208. X    if (*p == '.') {
  2209. X    fpos = 1.0/10.0;
  2210. X    p++;
  2211. X    while(isdigit(*p)) {
  2212. X        acc += (*p - '0') * fpos;
  2213. X        fpos *= 1.0/10.0;
  2214. X        p++;
  2215. X    }
  2216. X    }
  2217. X    if (*p == 'e' || *p == 'E') {
  2218. X    exp = 0;
  2219. X    exps = 1;
  2220. X        p++;
  2221. X    if (*p == '+')
  2222. X        p++;
  2223. X    else if (*p == '-') {
  2224. X        p++;
  2225. X        exps = -1;
  2226. X    }
  2227. X    while(isdigit(*p)) {
  2228. X        exp = exp * 10 + (*p - '0');
  2229. X        p++;
  2230. X    }
  2231. X    }
  2232. X    if (exp) {
  2233. X    if (exps > 0)
  2234. X        while (exp--)
  2235. X        acc *= 10.0;
  2236. X    else
  2237. X        while (exp--)
  2238. X        acc *= 1.0/10.0;
  2239. X    }
  2240. X    if (sign > 0)
  2241. X        *res = acc;
  2242. X    else
  2243. X    *res = -acc;
  2244. X
  2245. X    (void) signal(SIGFPE, sig_save);
  2246. X    return(p);
  2247. X}
  2248. END_OF_FILE
  2249.   if test 13128 -ne `wc -c <'lex.c'`; then
  2250.     echo shar: \"'lex.c'\" unpacked with wrong size!
  2251.   fi
  2252.   # end of 'lex.c'
  2253. fi
  2254. if test -f 'psc.c' -a "${1}" != "-c" ; then 
  2255.   echo shar: Will not clobber existing file \"'psc.c'\"
  2256. else
  2257.   echo shar: Extracting \"'psc.c'\" \(5741 characters\)
  2258.   sed "s/^X//" >'psc.c' <<'END_OF_FILE'
  2259. X/* Sc parse routine
  2260. X *
  2261. X * usage psc options
  2262. X * options:
  2263. X *   -L        Left justify strings.  Default is right justify.
  2264. X *   -r        Assemble data into rows first, not columns.
  2265. X *   -R    n    Increment by n between rows 
  2266. X *   -C n    Increment by n between columns
  2267. X *   -n n    Length of the row (column) should be n.
  2268. X *   -s v    Top left location in the spreadsheet should be v; eg, k5
  2269. X *   -d c       Use c as the delimiter between the fields.
  2270. X *   -k         Keep all delimiters - Default is strip multiple delimiters to 1.
  2271. X *   -f         suppress 'format' lines in output
  2272. X *   
  2273. X *  Author: Robert Bond
  2274. X *        $Revision: 6.8 $
  2275. X */
  2276. X
  2277. X#include <ctype.h>
  2278. X#include <stdio.h>
  2279. X#include "sc.h"
  2280. X
  2281. X#define END 0
  2282. X#define NUM 1
  2283. X#define ALPHA 2
  2284. X#define SPACE 3
  2285. X#define EOL 4
  2286. X
  2287. Xextern char *optarg;
  2288. Xextern int   optind;
  2289. Xchar *coltoa();
  2290. Xchar *progname;
  2291. X
  2292. X#ifdef SYSV3
  2293. Xextern void exit();
  2294. X#else
  2295. Xextern int exit();
  2296. X#endif
  2297. X
  2298. Xint colfirst = 0;
  2299. Xint r0 = 0;
  2300. Xint c0 = 0;
  2301. Xint rinc = 1;
  2302. Xint cinc = 1;
  2303. Xint leftadj = 0;
  2304. Xint len = 20000;
  2305. Xchar delim1 = ' ';
  2306. Xchar delim2 = '\t';
  2307. Xint strip_delim = 1;
  2308. Xint drop_format = 0;
  2309. Xint *fwidth;
  2310. Xint *precision;
  2311. Xint maxcols;
  2312. X
  2313. Xchar token[1000];
  2314. X
  2315. Xmain(argc, argv)
  2316. Xint argc;
  2317. Xchar **argv;
  2318. X{
  2319. X    int curlen;
  2320. X    int curcol, coff;
  2321. X    int currow, roff;
  2322. X    int first;
  2323. X    int c;
  2324. X    register effr, effc;
  2325. X    int i,j;
  2326. X    register char *p;
  2327. X
  2328. X    progname = argv[0];
  2329. X    while ((c = getopt(argc, argv, "rfLks:R:C:n:d:")) != EOF) {
  2330. X    switch(c) {
  2331. X    case 'r':
  2332. X        colfirst = 1;
  2333. X        break;
  2334. X    case 'L':
  2335. X        leftadj = 1;
  2336. X        break;
  2337. X    case 's':
  2338. X        c0 = getcol(optarg);
  2339. X        r0 = getrow(optarg);
  2340. X        break;
  2341. X    case 'R':
  2342. X        rinc = atoi(optarg);
  2343. X        break;
  2344. X    case 'C':
  2345. X        cinc = atoi(optarg);
  2346. X        break;
  2347. X    case 'n':
  2348. X        len = atoi(optarg);
  2349. X        break;
  2350. X    case 'd':
  2351. X        delim1 = optarg[0];
  2352. X        delim2 = 0;
  2353. X        break;
  2354. X    case 'k':
  2355. X        strip_delim = 0;
  2356. X        break;
  2357. X    case 'f':
  2358. X        drop_format = 1;
  2359. X        break;
  2360. X    default:
  2361. X        (void) fprintf(stderr,"Usage: %s [-rkfL] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
  2362. X        exit(1);
  2363. X        }
  2364. X    }
  2365. X
  2366. X    if (optind < argc) {
  2367. X        (void) fprintf(stderr,"Usage: %s [-rL] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
  2368. X        exit(1);
  2369. X    }
  2370. X
  2371. X    /* setup the spreadsheet arrays */
  2372. X    if (!growtbl(GROWNEW, 0, 0))
  2373. X    exit(1);
  2374. X
  2375. X    curlen = 0;
  2376. X    curcol = c0; coff = 0;
  2377. X    currow = r0; roff = 0;
  2378. X    first = 1;
  2379. X
  2380. X    while(1) {
  2381. X
  2382. X    effr = currow+roff;
  2383. X    effc = curcol+coff;
  2384. X
  2385. X    switch(scan()) {
  2386. X    case END:
  2387. X        if(drop_format) exit(0);
  2388. X        for (i = 0; i<maxcols; i++) {
  2389. X        if (precision[i])
  2390. X            (void) printf("format %s %d %d\n", coltoa(i), 
  2391. X            fwidth[i], precision[i]+1);
  2392. X        }
  2393. X        exit(0);
  2394. X    case NUM:
  2395. X        first = 0;
  2396. X        (void) printf("let %s%d = %s\n", coltoa(effc), effr, token);
  2397. X        if (effc >= maxcols - 1)
  2398. X        {    if (!growtbl(GROWCOL, 0, 0))
  2399. X        {    (void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
  2400. X            continue;
  2401. X        }
  2402. X        }
  2403. X        i = 0;
  2404. X        j = 0;
  2405. X        p = token;
  2406. X        while (*p && *p != '.') {
  2407. X        p++; i++;
  2408. X        }
  2409. X        if (*p) {
  2410. X        p++; i++;
  2411. X        }
  2412. X        while (*p) {
  2413. X        p++; i++; j++;
  2414. X        }
  2415. X        if (precision[effc] < j)
  2416. X        precision[effc] = j;
  2417. X        if (fwidth[effc] < i)
  2418. X        fwidth[effc] = i;
  2419. X        break;
  2420. X    case ALPHA:
  2421. X        first = 0;
  2422. X        if (leftadj)
  2423. X        (void) printf("leftstring %s%d = \"%s\"\n", coltoa(effc),effr,token); 
  2424. X        else
  2425. X        (void) printf("rightstring %s%d = \"%s\"\n",coltoa(effc),effr,token); 
  2426. X        if (effc >= maxcols - 1)
  2427. X        {    if (!growtbl(GROWCOL, 0, 0))
  2428. X        {    (void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
  2429. X            continue;
  2430. X        }
  2431. X        }
  2432. X        i = strlen(token);
  2433. X        if (i > precision[effc])
  2434. X        precision[effc] = i;
  2435. X        break;
  2436. X    case SPACE:
  2437. X        if (first && strip_delim)
  2438. X        break;
  2439. X        if (colfirst)
  2440. X        roff++;
  2441. X        else
  2442. X        coff++;
  2443. X        break;
  2444. X    case EOL:
  2445. X        curlen++;
  2446. X        roff = 0;
  2447. X        coff = 0;
  2448. X        first = 1;
  2449. X        if (colfirst) {
  2450. X        if (curlen >= len) {
  2451. X            curcol = c0;
  2452. X            currow += rinc;
  2453. X            curlen = 0;
  2454. X        } else {
  2455. X            curcol += cinc;
  2456. X        }
  2457. X        } else {
  2458. X        if (curlen >= len) {
  2459. X            currow = r0;
  2460. X            curcol += cinc;
  2461. X            curlen = 0;
  2462. X        } else {
  2463. X            currow += rinc;
  2464. X        }
  2465. X        }
  2466. X        break;
  2467. X    }
  2468. X    }
  2469. X}
  2470. X
  2471. Xscan()
  2472. X{
  2473. X    register int c;
  2474. X    register char *p;
  2475. X
  2476. X    p = token;
  2477. X    c = getchar();
  2478. X
  2479. X    if (c == EOF)
  2480. X    return(END);
  2481. X
  2482. X    if (c == '\n')
  2483. X    return(EOL);
  2484. X
  2485. X    if (c == delim1 || c == delim2) {
  2486. X        if (strip_delim) {
  2487. X        while ((c = getchar()) && (c == delim1 || c == delim2))
  2488. X            ;
  2489. X        (void)ungetc(c, stdin);
  2490. X    } 
  2491. X    return(SPACE);
  2492. X    }
  2493. X
  2494. X    if (c == '\"') {
  2495. X    while ((c = getchar()) && c != '\"' && c != '\n' && c != EOF)
  2496. X        *p++ = c;
  2497. X    if (c != '\"')
  2498. X        (void)ungetc(c, stdin);
  2499. X    *p = 0;
  2500. X    return(ALPHA);
  2501. X    }
  2502. X
  2503. X    while (c != delim1 && c != delim2 && c!= '\n' && c != EOF) {
  2504. X    *p++ = c;
  2505. X    c = getchar();
  2506. X    }
  2507. X    *p = 0;
  2508. X    (void)ungetc(c, stdin);
  2509. X
  2510. X    p = token;
  2511. X    c = *p;
  2512. X    if (isdigit(c) || c == '.' || c == '-' || c == '+') {
  2513. X    while(isdigit(c) || c == '.' || c == '-' || c == '+' || c == 'e'
  2514. X        || c == 'E') {
  2515. X        c = *p++;
  2516. X    }
  2517. X    if (c == 0)
  2518. X        return(NUM);
  2519. X    else
  2520. X        return(ALPHA);
  2521. X    }
  2522. X
  2523. X    return(ALPHA);
  2524. X}
  2525. X    
  2526. Xgetcol(p)
  2527. Xchar *p;
  2528. X{
  2529. X    register  col;
  2530. X
  2531. X    if (!p)
  2532. X    return(0);
  2533. X    while(*p && !isalpha(*p)) 
  2534. X    p++; 
  2535. X    if (!*p)
  2536. X    return(0);
  2537. X    col = ((*p & 0137) - 'A');
  2538. X    if (isalpha(*++p)) 
  2539. X    col = (col + 1)*26 + ((*p & 0137) - 'A');
  2540. X    return(col);
  2541. X}
  2542. X
  2543. Xgetrow(p)
  2544. Xchar *p;
  2545. X{
  2546. X    int row;
  2547. X
  2548. X    if (!p)
  2549. X    return(0);
  2550. X    while(*p && !isdigit(*p))
  2551. X    p++; 
  2552. X    if (!*p)
  2553. X    return(0);
  2554. X    if (sscanf(p, "%d", &row) != 1)
  2555. X    return(0);
  2556. X    return(row);
  2557. X}
  2558. X
  2559. Xchar *
  2560. Xcoltoa(col)
  2561. Xint col;
  2562. X{
  2563. X    static char rname[3];
  2564. X    register char *p = rname;
  2565. X
  2566. X    if (col < 0 || col > 25*26) 
  2567. X    (void) fprintf(stderr,"coltoa: invalid col: %d", col);
  2568. X
  2569. X    if (col > 25) {
  2570. X    *p++ = col/26 + 'A' - 1;
  2571. X    col %= 26;
  2572. X    }
  2573. X    *p++ = col+'A';
  2574. X    *p = 0;
  2575. X    return(rname);
  2576. X}
  2577. X
  2578. END_OF_FILE
  2579.   if test 5741 -ne `wc -c <'psc.c'`; then
  2580.     echo shar: \"'psc.c'\" unpacked with wrong size!
  2581.   fi
  2582.   # end of 'psc.c'
  2583. fi
  2584. if test -f 'xmalloc.c' -a "${1}" != "-c" ; then 
  2585.   echo shar: Will not clobber existing file \"'xmalloc.c'\"
  2586. else
  2587.   echo shar: Extracting \"'xmalloc.c'\" \(686 characters\)
  2588.   sed "s/^X//" >'xmalloc.c' <<'END_OF_FILE'
  2589. X/*
  2590. X * A safer saner malloc, for careless programmers
  2591. X * $Revision: 6.8 $
  2592. X */
  2593. X
  2594. X#include <stdio.h>
  2595. X#include <curses.h>
  2596. X#include "sc.h"
  2597. X
  2598. Xextern char *malloc();
  2599. X
  2600. X#ifdef SYSV3
  2601. Xextern void free();
  2602. Xextern void exit();
  2603. X#endif
  2604. X
  2605. Xchar *
  2606. Xxmalloc(n)
  2607. Xunsigned n;
  2608. X{
  2609. Xregister char *ptr;
  2610. X
  2611. Xif ((ptr = malloc(n + sizeof(double))) == NULL)
  2612. X    fatal("xmalloc: no memory");
  2613. X*((int *) ptr) = 12345;        /* magic number */
  2614. Xreturn(ptr + sizeof(double));
  2615. X}
  2616. X
  2617. Xxfree(p)
  2618. Xchar *p;
  2619. X{
  2620. Xif (p == NULL)
  2621. X    fatal("xfree: NULL");
  2622. Xp -= sizeof(double);
  2623. Xif (*((int *) p) != 12345)
  2624. X    fatal("xfree: storage not malloc'ed");
  2625. Xfree(p);
  2626. X}
  2627. X
  2628. Xfatal(str)
  2629. Xchar *str;
  2630. X{
  2631. X    deraw();
  2632. X    (void) fprintf(stderr,"%s\n", str);
  2633. X    exit(1);
  2634. X}
  2635. END_OF_FILE
  2636.   if test 686 -ne `wc -c <'xmalloc.c'`; then
  2637.     echo shar: \"'xmalloc.c'\" unpacked with wrong size!
  2638.   fi
  2639.   # end of 'xmalloc.c'
  2640. fi
  2641. echo shar: End of archive 4 \(of 6\).
  2642. cp /dev/null ark4isdone
  2643. MISSING=""
  2644. for I in 1 2 3 4 5 6 ; do
  2645.     if test ! -f ark${I}isdone ; then
  2646.     MISSING="${MISSING} ${I}"
  2647.     fi
  2648. done
  2649. if test "${MISSING}" = "" ; then
  2650.     echo You have unpacked all 6 archives.
  2651.     rm -f ark[1-9]isdone
  2652. else
  2653.     echo You still must unpack the following archives:
  2654.     echo "        " ${MISSING}
  2655. fi
  2656. exit 0
  2657. exit 0 # Just in case...
  2658.